home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK2.toast / Development Kits (Disc 2) / TEC 1.2.1 / Sample Code / UnicodeHub / UnicodeHub.cp < prev    next >
Encoding:
Text File  |  1997-11-18  |  41.0 KB  |  1,429 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        UnicodeHub.cp
  3.  
  4.     Contains:    
  5.  
  6.     Version:    System 8
  7.  
  8.     Copyright:    © 1997 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     File Ownership:
  11.  
  12.         DRI:                Julio Gonzalez
  13.  
  14.         Other Contact:        Andrew Daniels
  15.  
  16.         Technology:            International
  17.  
  18.     Writers:
  19.  
  20.         (jag)    Julio Gonzalez
  21.  
  22.     Change History (most recent first):
  23.  
  24.          <2>     8/20/97    jag        Change the style from outline to bold when displaying strings
  25.                                     that are encoded in non-Mac OS encodings.
  26. */
  27.  
  28. // ===========================================================================
  29. //    <PP Starter Source>.cp         ©1994-1995 Metrowerks Inc. All rights reserved.
  30. // ===========================================================================
  31. //
  32. //    This file contains the starter code for a PowerPlant application
  33.  
  34. #include "UnicodeHub.h"
  35. #include "UnicodeHubConstants.h"
  36.  
  37. #include <Sound.h>
  38. #include <Script.h>                            // Script Manager definitions
  39.  
  40. #include <LGrowZone.h>
  41. #include <LWindow.h>
  42. #include <PP_Messages.h>
  43. #include <PP_Resources.h>
  44. #include <PPobClasses.h>
  45. #include <UDrawingState.h>
  46. #include <UMemoryMgr.h>
  47. #include <UReanimator.h>
  48. #include <UDesktop.h>
  49. #include <URegistrar.h>
  50. #include <LEditField.h>
  51. #include <LTextEdit.h>
  52. #include <UTextTraits.h>
  53. #include <LDynamicArray.h>
  54.  
  55. unsigned char UnicodeErrors [][32] = {
  56.     "\p",
  57.     "\p",
  58.     "\p",
  59.     "\p",
  60.     "\pkTECOutputBufferFullStatus",
  61.     "\pkTECNeedFlushStatus",
  62.     "\pkTECUsedFallbacksStatus",
  63.     "\p",
  64.     "\p",
  65.     "\p",
  66.     "\p",
  67.     "\p",
  68.     "\p",
  69.     "\p",
  70.     "\p",
  71.     "\p",
  72.     "\p",
  73.     "\p",
  74.     "\pkTECItemUnavailableErr",
  75.     "\pkTECGlobalsUnavailableErr",    
  76.     "\punicodeChecksumErr",
  77.     "\punicodeNoTableErr",
  78.     "\punicodeVariantErr",
  79.     "\punicodeFallbacksErr",
  80.     "\punicodePartConvertErr",
  81.     "\punicodeBufErr",
  82.     "\punicodeCharErr",
  83.     "\punicodeElementErr",
  84.     "\punicodeNotFoundErr",
  85.     "\punicodeTableFormatErr",
  86.     "\punicodeDirectionErr",
  87.     "\punicodeContextualErr",
  88.     "\punicodeTextEncodingDataErr",
  89.     "\pkTECDirectionErr",
  90.     "\pkTECIncompleteElementErr",
  91.     "\pkTECUnmappableElementErr",
  92.     "\pkTECPartialCharErr",
  93.     "\pkTECBadTextRunErr",
  94.     "\pkTECArrayFullErr",
  95.     "\pkTECBufferBelowMinimumSizeErr",
  96.     "\pkTECNoConversionPathErr",
  97.     "\pkTECCorruptConverterErr",
  98.     "\pkTECTableFormatErr",
  99.     "\pkTECTableChecksumErr",
  100.     "\pkTECMissingTableErr",
  101.     "\p",
  102.     "\p",
  103.     "\p",
  104.     "\p",
  105.     "\kTextUndefinedElementErrp",
  106.     "\pkTextMalformedInputErr",
  107.     "\pkTextUnsupportedEncodingErr",
  108.     
  109.     "\pkIllegalHexString"
  110. };
  111.  
  112.  
  113.  
  114.  
  115. CPPStarterApp*    gTheApp=0;
  116.  
  117.  
  118.  
  119. // ===========================================================================
  120. //        • Main Program
  121. // ===========================================================================
  122.  
  123. void main(void)
  124. {
  125.                                     // Set Debugging options
  126.     SetDebugThrow_(debugAction_Alert);
  127.     SetDebugSignal_(debugAction_Nothing);
  128.  
  129.     InitializeHeap(3);                // Initialize Memory Manager
  130.                                     // Parameter is number of Master Pointer
  131.                                     //   blocks to allocate
  132.     
  133.                                     // Initialize standard Toolbox managers
  134.     UQDGlobals::InitializeToolbox(&qd);
  135.     
  136.     new LGrowZone(20000);            // Install a GrowZone function to catch
  137.                                     //    low memory situations.
  138.  
  139.     CPPStarterApp    theApp;            // replace this with your App type
  140.     
  141.     gTheApp = &theApp;                // Save a pointer to the application -- there might be a better
  142.                                     // way to get a the app -- like getting to the top level commander?
  143.  
  144.     theApp.GetMappings();            // Get all the available Unicode Mappings
  145.     
  146.     theApp.Run();
  147. }
  148.  
  149.  
  150. // ---------------------------------------------------------------------------
  151. //        • CPPStarterApp             // replace this with your App type
  152. // ---------------------------------------------------------------------------
  153.  
  154. //    Constructor
  155.  
  156. CPPStarterApp::CPPStarterApp()
  157. {
  158.     // Register functions to create core PowerPlant classes
  159.     
  160.     RegisterAllPPClasses();
  161.  
  162.     URegistrar::RegisterClass(
  163.             CUnicodeTablesPopup::class_ID,
  164.             (ClassCreatorFunc) CUnicodeTablesPopup::CreateUnicodeTablesPopupStream );
  165.     
  166.     URegistrar::RegisterClass(
  167.             CFontMenuPopup::class_ID,
  168.             (ClassCreatorFunc) CFontMenuPopup::CreateFontMenuPopupStream );
  169.     
  170.     URegistrar::RegisterClass(
  171.             CUnicodeHubWindow::class_ID,
  172.             (ClassCreatorFunc) CUnicodeHubWindow::CreateUnicodeHubWindowStream );
  173.     
  174.     URegistrar::RegisterClass(
  175.             CStyleText::class_ID,
  176.             (ClassCreatorFunc) CStyleText::CreateStyleTextEditStream );
  177.     
  178.     
  179. }
  180.  
  181.  
  182. // ---------------------------------------------------------------------------
  183. //        • ~CPPStarterApp            // replace this with your App type
  184. // ---------------------------------------------------------------------------
  185. //    Destructor
  186. //
  187.  
  188. CPPStarterApp::~CPPStarterApp()
  189. {
  190. }
  191.  
  192. // ---------------------------------------------------------------------------
  193. //        • StartUp
  194. // ---------------------------------------------------------------------------
  195. //    This function lets you do something when the application starts up. 
  196. //    For example, you could issue your own new command, or respond to a system
  197. //  oDoc (open document) event.
  198.  
  199. void
  200. CPPStarterApp::StartUp()
  201. {
  202.     ObeyCommand(cmd_New, nil);        // EXAMPLE, create a new window
  203. }
  204.  
  205. // ---------------------------------------------------------------------------
  206. //        • ObeyCommand
  207. // ---------------------------------------------------------------------------
  208. //    Respond to commands
  209.  
  210. Boolean
  211. CPPStarterApp::ObeyCommand(
  212.     CommandT    inCommand,
  213.     void        *ioParam)
  214. {
  215.     Boolean        cmdHandled = true;
  216.  
  217.     switch (inCommand) {
  218.     
  219.         // Deal with command messages (defined in PP_Messages.h).
  220.         // Any that you don't handle will be passed to LApplication
  221.              
  222.         case cmd_New:
  223.                                         // EXAMPLE, create a new window
  224.             CUnicodeHubWindow    *theWindow;
  225.             theWindow = (CUnicodeHubWindow    *)CUnicodeHubWindow::CreateWindow(rPPob_UnicodeHubWindow, this);    
  226.             UReanimator::LinkListenerToControls( (CUnicodeHubWindow*)theWindow, (LWindow*)theWindow, rRidL_UnicodeHubWindow);
  227.             theWindow->Show();
  228.             break;
  229.  
  230.  
  231.  
  232.         default:
  233.             cmdHandled = LApplication::ObeyCommand(inCommand, ioParam);
  234.             break;
  235.     }
  236.     
  237.     return cmdHandled;
  238. }
  239.  
  240. // ---------------------------------------------------------------------------
  241. //        • FindCommandStatus
  242. // ---------------------------------------------------------------------------
  243. //    This function enables menu commands.
  244. //
  245.  
  246. void
  247. CPPStarterApp::FindCommandStatus(
  248.     CommandT    inCommand,
  249.     Boolean        &outEnabled,
  250.     Boolean        &outUsesMark,
  251.     Char16        &outMark,
  252.     Str255        outName)
  253. {
  254.  
  255.     switch (inCommand) {
  256.     
  257.         // Return menu item status according to command messages.
  258.         // Any that you don't handle will be passed to LApplication
  259.  
  260.         case cmd_New:                    // EXAMPLE
  261.             outEnabled = false;            // disable the New command - currently PP crashes when the 2nd
  262.                                         // window comes up - so disable it it - I don't need 2 windows
  263.             break;
  264.  
  265.         default:
  266.             LApplication::FindCommandStatus(inCommand, outEnabled,
  267.                                                 outUsesMark, outMark, outName);
  268.             break;
  269.     }
  270. }
  271.  
  272.  
  273.  
  274. // ---------------------------------------------------------------------------------
  275. //        • GetMappings
  276. // ---------------------------------------------------------------------------------
  277.  
  278. void PrepareForMenuDisplay( StringPtr str );
  279. void PrepareForMenuDisplay( StringPtr str )
  280. {
  281.     int    len=*str;
  282.     
  283.     while(len>0)
  284.     {
  285.         str++;
  286.         if( *str == '\/' || *str == '\\')
  287.             *str = '-';
  288.         if( *str == '(' )
  289.             *str = '[';
  290.         if( *str == ')' )
  291.             *str = ']';
  292.         len--;
  293.     }
  294. }
  295.  
  296.  
  297. OSStatus
  298. CPPStarterApp::GetMappings()
  299. {
  300.     OSStatus            status;
  301.     ByteCount            outputLen;
  302.     UnicodeMapping        findMapping = {0};
  303.     short                i=0;
  304.     int                    position;    
  305.  
  306.     /**********************************************************************************************************
  307.      *    TEC SPECIFIC CODE COMMENT
  308.      *
  309.      *    Obtain a list of all the available encoding conversions that we may be able to perform.
  310.      *  This includes, all conversions that the Text Encoding Converter and the Unicode Converter
  311.      *  can perform.  First I call TECCountAvailableTextEncodings to get the number of encodings that
  312.      *    are supported.  I really don't need to do that sinve I've statically allocated the size of the
  313.      *    buffer.  However, we presume that most people will need to make this call to assertain how big
  314.      *    of a buffer to allocate before calling TECGetAvailableTextEncodings.
  315.      **********************************************************************************************************/
  316.     
  317.     status = TECCountAvailableTextEncodings( &mNumMappings);
  318.     ThrowIfError_(status);
  319.     
  320.     status = TECGetAvailableTextEncodings(mAvailableMappings, mNumMappings, &mNumMappings);
  321.     ThrowIfError_(status);
  322.  
  323.     /**********************************************************************************************************
  324.      *    END TEC SPECIFIC CODE COMMENTED BLOCK
  325.      **********************************************************************************************************/
  326.  
  327.  
  328. //**** LAME SORT - sort all the encodings returned by the Text Encoding numerical value.
  329.     LDynamicArray    *myMappingsList=new LDynamicArray( (Uint32)( sizeof(mAvailableMappings[0]) ) );
  330.     
  331.     i=0;
  332.     while( i++< mNumMappings )
  333.     {
  334.         TextEncoding    theMapping;
  335.         
  336.         for ( position=1; position<=myMappingsList->GetCount(); position++ )
  337.         {
  338.             myMappingsList->FetchItemAt( position, &theMapping );
  339.             if( theMapping < mAvailableMappings[i-1] )
  340.                 break;
  341.         }
  342.         
  343.         myMappingsList->InsertItemsAt( 1, position, &mAvailableMappings[i-1] );
  344.     }
  345.     
  346.     i=0;
  347.     position =mNumMappings;
  348.     while(i++<mNumMappings)
  349.     {    
  350.         myMappingsList->FetchItemAt( position--, &mAvailableMappings[i-1] );
  351.     }    
  352.     
  353.     delete myMappingsList;
  354. //*** END OF LAME SORT
  355.     
  356.     /**********************************************************************************************************
  357.      *    TEC SPECIFIC CODE COMMENT
  358.      *
  359.      *    In the following loop, we'll get the name for every one of the encodings in our array.  We use the
  360.      *    GetTextEncodingName name API.  Currently, most tables/plugins have defined in them a name in the
  361.      *    kTextEncodingUS_ASCII encoding.  We also check for kTextEncodingMacRoman just in case.
  362.      *    First we get the name for the base encoding, later we proceed to get the name for the variant and 
  363.      *    format if any.  Currently, there are no names for variant and formats entered in the tables.  So, I've
  364.      *    added code that just displays the HEX value for the encoding.
  365.      **********************************************************************************************************/
  366.  
  367.     i=0;
  368.     while(i++<mNumMappings)
  369.     {
  370.         TextEncoding    nameEncoding;
  371.         RegionCode         oActualRegion;
  372.         
  373.         //Get the name of the encoding base
  374.         status = GetTextEncodingName(mAvailableMappings[i-1], kTextEncodingBaseName, verUS, kTextEncodingUS_ASCII,
  375.             kMaxLen, &outputLen,  &oActualRegion,&nameEncoding, (TextPtr) (mAvailableMappingNames[i-1])+1);
  376.  
  377.         if( status == noErr && (  nameEncoding == kTextEncodingMacRoman || nameEncoding == kTextEncodingUS_ASCII))
  378.         {
  379.             Str63    variantFormatName;
  380.             ByteCount    oldOutputLen=outputLen;
  381.             
  382.             *((mAvailableMappingNames[i-1]))=outputLen;
  383.  
  384.             //Get the name of the variant
  385.             status = GetTextEncodingName(mAvailableMappings[i-1], kTextEncodingVariantName, verUS, kTextEncodingUS_ASCII,
  386.             kMaxLen, &outputLen,  &oActualRegion,&nameEncoding, (TextPtr) (variantFormatName)+1);
  387.             if( status == noErr )
  388.             {
  389.                 BlockMove( (variantFormatName)+1, ((mAvailableMappingNames[i-1]))+*((mAvailableMappingNames[i-1]))+1, outputLen );
  390.                 *((mAvailableMappingNames[i-1]))+=outputLen;
  391.             }
  392.                 
  393.             //Get the name of the format
  394.             status = GetTextEncodingName(mAvailableMappings[i-1], kTextEncodingFormatName, verUS, kTextEncodingUS_ASCII,
  395.             kMaxLen, &outputLen,  &oActualRegion,&nameEncoding, (TextPtr) (variantFormatName)+1);
  396.             if( status == noErr )
  397.             {
  398.                 BlockMove( (variantFormatName)+1, ((mAvailableMappingNames[i-1]))+*((mAvailableMappingNames[i-1]))+1, outputLen );
  399.                 *((mAvailableMappingNames[i-1]))+=outputLen;
  400.             }
  401.  
  402.  
  403.             //If the encoding has either a base or a variant but no text was returned from the calls
  404.             //above, then append the encoding number in Hex.
  405.             if( ( ( GetTextEncodingVariant(mAvailableMappings[i-1]) != kTextEncodingDefaultVariant) ||
  406.                 ( GetTextEncodingFormat(mAvailableMappings[i-1]) != kTextEncodingDefaultFormat) ) &&
  407.                 oldOutputLen == *((mAvailableMappingNames[i-1])) )
  408.             {    
  409.                 BlockMove( " 0x", ((mAvailableMappingNames[i-1]))+*((mAvailableMappingNames[i-1]))+1, 3);
  410.                 BufToHex( (unsigned char*)&mAvailableMappings[i-1], (unsigned char*)  ((mAvailableMappingNames[i-1]))+*((mAvailableMappingNames[i-1]))+4,
  411.                     4, outputLen, 0);
  412.                 *((mAvailableMappingNames[i-1]))+=11;
  413.             }
  414.  
  415.             PrepareForMenuDisplay( mAvailableMappingNames[i-1] );
  416.         }
  417.         else
  418.         {
  419.             *((mAvailableMappingNames[i-1]))=10;
  420.             ::BlockMove( "0x", (((mAvailableMappingNames[i-1]))+1), 2);
  421.             BufToHex( (unsigned char*)&mAvailableMappings[i-1], (unsigned char*) (((mAvailableMappingNames[i-1]))+3),
  422.                 4, outputLen, 0);
  423.             PrepareForMenuDisplay( mAvailableMappingNames[i-1] );
  424.         }
  425.     }
  426.     /**********************************************************************************************************
  427.      *    END TEC SPECIFIC CODE COMMENTED BLOCK
  428.      **********************************************************************************************************/
  429.     
  430.  
  431. error:    
  432.     return status;
  433. }
  434.  
  435.  
  436. /********************************************************
  437.                 OptionKeyDown
  438. ********************************************************/
  439. Boolean OptionKeyDown(void);
  440. Boolean OptionKeyDown(void)
  441. {
  442.     return ((*(long *)0x178 & 4L) != 0L);
  443. }
  444.  
  445.  
  446. #define PLAYSOUND 0
  447.  
  448. void CPPStarterApp::ShowAboutBox()
  449. {
  450.     //inherited::ShowAboutBox();
  451.     
  452. #if PLAYSOUND
  453.     Handle    theSound=::GetNamedResource('snd ',"\pAboutSound");
  454.     if(theSound)
  455.         ::HNoPurge(theSound);
  456. #endif
  457.  
  458.     UDesktop::Deactivate();        // Alert will swallow Deactivate event
  459.     
  460.     
  461.     DialogPtr dPtr=::GetNewDialog( ALRT_About, nil, (WindowPtr)-1L);
  462.     FailNIL_( dPtr );
  463.     
  464.     ::SetDialogDefaultItem( dPtr, 1);
  465.     ::DrawDialog(dPtr);
  466.     
  467. #if PLAYSOUND
  468.     if(theSound)
  469.     {
  470.         ::SetCursor(*(::GetCursor(watchCursor)));
  471.         ::SndPlay( nil, (SndListResource**)theSound, false);
  472.         ::HPurge(theSound);
  473.         ::ReleaseResource( theSound );
  474.         ::InitCursor();
  475.     }
  476. #endif
  477.     
  478.     short    itemHit=0;
  479.     while(itemHit!=1)
  480.         ::ModalDialog( nil, &itemHit );
  481.         
  482.     if( OptionKeyDown() )
  483.         DebugStr("\pLet's do some debugging");
  484.  
  485.     DisposeDialog( dPtr );
  486.     
  487.     UDesktop::Activate();
  488. }
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495. // *********************************************************************************
  496. //        • CUnicodeTablesPopup
  497. // *********************************************************************************
  498.  
  499.  
  500. CUnicodeTablesPopup*
  501. CUnicodeTablesPopup::CreateUnicodeTablesPopupStream(LStream *inStream)
  502. {
  503.     return ( new CUnicodeTablesPopup( inStream ));
  504. }
  505.  
  506. CUnicodeTablesPopup::CUnicodeTablesPopup(const SPaneInfo &inPaneInfo,
  507.                     MessageT inValueMessage, Int16 inTitleOptions,
  508.                     ResIDT inMENUid, Int16 inTitleWidth,
  509.                     Int16 inPopupVariation, ResIDT inTextTraitsID,
  510.                     Str255 inTitle, OSType inResTypeMENU,
  511.                     Int16 inInitialMenuItem) :
  512.      LStdPopupMenu(inPaneInfo, inValueMessage, inTitleOptions,
  513.                 inMENUid, inTitleWidth, inPopupVariation, inTextTraitsID,
  514.                 inTitle, inResTypeMENU, inInitialMenuItem)
  515. {
  516.     FillMenuWithUnicodeTables();
  517. }
  518.                     
  519. CUnicodeTablesPopup::CUnicodeTablesPopup(const SPaneInfo &inPaneInfo,
  520.                     MessageT inValueMessage, Int32 inMaxValue,
  521.                     ResIDT inTextTraitsID, ControlHandle inMacControlH ) :
  522.             LStdPopupMenu(inPaneInfo, inValueMessage, inMaxValue,
  523.                         inTextTraitsID, inMacControlH)
  524. {
  525.     FillMenuWithUnicodeTables();
  526. }
  527.  
  528.                     
  529. CUnicodeTablesPopup::CUnicodeTablesPopup(LStream *inStream) : LStdPopupMenu( inStream )
  530. {
  531.     FillMenuWithUnicodeTables();
  532. }
  533.  
  534.  
  535.  
  536. CUnicodeTablesPopup::~CUnicodeTablesPopup()
  537. {
  538. }
  539.  
  540. void CUnicodeTablesPopup::FillMenuWithUnicodeTables(void)
  541. {
  542.     MenuHandle    theMenuH=GetMacMenuH();
  543.     
  544.     if(!theMenuH)    return;
  545.     
  546.     
  547.     for( UInt32 i=0; i<gTheApp->mNumMappings; i++)
  548.     {
  549.         ::InsertMenuItem(theMenuH, gTheApp->mAvailableMappingNames[i], i+2);
  550.         if( gTheApp->IsUnicode(    gTheApp->mAvailableMappings[i] ) )
  551.             ::SetItemStyle( theMenuH, i+2, bold );
  552.     }
  553.     
  554.     SetMaxValue(gTheApp->mNumMappings+1);
  555. }
  556.  
  557.  
  558. // *********************************************************************************
  559. //        • CFontMenuPopup
  560. // *********************************************************************************
  561.  
  562.  
  563. CFontMenuPopup*
  564. CFontMenuPopup::CreateFontMenuPopupStream(LStream *inStream)
  565. {
  566.     return ( new CFontMenuPopup( inStream ));
  567. }
  568.  
  569. CFontMenuPopup::CFontMenuPopup(const SPaneInfo &inPaneInfo,
  570.                     MessageT inValueMessage, Int16 inTitleOptions,
  571.                     ResIDT inMENUid, Int16 inTitleWidth,
  572.                     Int16 inPopupVariation, ResIDT inTextTraitsID,
  573.                     Str255 inTitle, OSType inResTypeMENU,
  574.                     Int16 inInitialMenuItem) :
  575.      LStdPopupMenu(inPaneInfo, inValueMessage, inTitleOptions,
  576.                 inMENUid, inTitleWidth, inPopupVariation, inTextTraitsID,
  577.                 inTitle, inResTypeMENU, inInitialMenuItem)
  578. {
  579.     FillFontMenu();
  580. }
  581.                     
  582. CFontMenuPopup::CFontMenuPopup(const SPaneInfo &inPaneInfo,
  583.                     MessageT inValueMessage, Int32 inMaxValue,
  584.                     ResIDT inTextTraitsID, ControlHandle inMacControlH ) :
  585.             LStdPopupMenu(inPaneInfo, inValueMessage, inMaxValue,
  586.                         inTextTraitsID, inMacControlH)
  587. {
  588.     FillFontMenu();
  589. }
  590.  
  591.                     
  592. CFontMenuPopup::CFontMenuPopup(LStream *inStream) : LStdPopupMenu( inStream )
  593. {
  594.     FillFontMenu();
  595. }
  596.  
  597.  
  598.  
  599. CFontMenuPopup::~CFontMenuPopup()
  600. {
  601. }
  602.  
  603.  
  604.  
  605. void CFontMenuPopup::FillFontMenu(void)
  606. {
  607.     UInt16        fontsInstalled;
  608.     UInt16        applFontIndex=1;
  609.     MenuHandle    theMenuH=GetMacMenuH();
  610.     
  611.     if(!theMenuH)    return;
  612.         
  613.     ::AppendResMenu( theMenuH, 'FONT');
  614.     fontsInstalled=::CountMItems(theMenuH);
  615.     SetMaxValue(fontsInstalled);
  616.         
  617.     /**********************************************************************************************************
  618.      *    TEC SPECIFIC CODE COMMENT
  619.      *
  620.      *    Here we loop through the font menu and build an array with TextEncodings that match every one
  621.      *    of the Font menu names.  In order to do this we use UpgradeScriptInfoToTextEncoding.  Also, just for
  622.      *    kicks, I check to see if the encoding has a variant or that doesn't correspond to a Mac script code.
  623.      *    If so, I make the item italic and bold for easy identification.
  624.      **********************************************************************************************************/
  625.     for( int i=1; i<=fontsInstalled; i++ )
  626.     {
  627.         Str31            fontName;
  628.         OSStatus        status;
  629.         TextEncoding    theEncoding;
  630.         
  631.         ::GetMenuItemText(theMenuH, i, fontName);
  632.         ::GetFNum(fontName, &mInstalledFonts[i-1] ) ;
  633.         
  634.         if( GetAppFont() == mInstalledFonts[i-1] )
  635.             applFontIndex=i;
  636.         
  637.         status = UpgradeScriptInfoToTextEncoding( kTextScriptDontCare, kTextLanguageDontCare, kTextRegionDontCare, fontName, &theEncoding );
  638.         if( status == noErr )
  639.         {
  640.             if( (theEncoding > smUninterp) || (GetTextEncodingVariant(theEncoding) != kTextEncodingDefaultVariant) )
  641.                 ::SetItemStyle( theMenuH, i, bold+italic);
  642.         }
  643.         else
  644.             ::SetItemStyle( theMenuH, i, outline );
  645.  
  646.     }
  647.     /**********************************************************************************************************
  648.      *    END TEC SPECIFIC CODE COMMENTED BLOCK
  649.      **********************************************************************************************************/
  650.      
  651.     LStdPopupMenu::SetValue( applFontIndex );
  652. }
  653.  
  654. ScriptCode CFontMenuPopup::GetSelectedScript(void)
  655. {
  656.     return ::FontToScript(mInstalledFonts[this->GetValue()-1]);
  657. }
  658.  
  659. void CFontMenuPopup::SetMValue(ScriptCode theCode)
  660. {
  661.     int i;
  662.     MenuHandle    menuH=this->GetMacMenuH();
  663.  
  664.     int maxItems=::CountMItems(menuH);
  665.     for( i=0; i<maxItems; i++ )
  666.         if( theCode ==  ::FontToScript( mInstalledFonts[i] ) )
  667.             break;
  668.  
  669.     LStdPopupMenu::SetValue( i+1 );
  670. }
  671.  
  672. void CFontMenuPopup::SetValueByFont(SInt16    theFont)
  673. {
  674.     int i;
  675.     MenuHandle    menuH=this->GetMacMenuH();
  676.  
  677.     int maxItems=::CountMItems(menuH);
  678.     for( i=0; i<maxItems; i++ )
  679.         if( theFont == mInstalledFonts[i] )
  680.             break;
  681.  
  682.     LStdPopupMenu::SetValue( i+1 );
  683. }
  684.  
  685.  
  686. // *********************************************************************************
  687. //        • CUnicodeHubWindow
  688. // *********************************************************************************
  689.  
  690.  
  691. // ---------------------------------------------------------------------------------
  692. //        • CreateUnicodeHubWindowStream
  693. // ---------------------------------------------------------------------------------
  694. CUnicodeHubWindow*
  695. CUnicodeHubWindow::CreateUnicodeHubWindowStream(LStream *inStream)
  696. {
  697.     return( new CUnicodeHubWindow( inStream ) );
  698. }
  699.  
  700. // ---------------------------------------------------------------------------------
  701. //        • CUnicodeHubWindow
  702. // ---------------------------------------------------------------------------------
  703. void CUnicodeHubWindow::InitUnicodeHubWindow(void)
  704. {
  705.     mFromUnicodeFlags=0;
  706.     mToUnicodeFlags=0;
  707. }
  708.  
  709.  
  710. CUnicodeHubWindow::CUnicodeHubWindow(LStream *inStream) :
  711.     LWindow( inStream )
  712. {
  713.     InitUnicodeHubWindow();
  714. }
  715.  
  716. CUnicodeHubWindow::CUnicodeHubWindow(
  717.         const SWindowInfo    &inWindowInfo) :
  718.     LWindow( inWindowInfo )
  719. {
  720.     InitUnicodeHubWindow();
  721. }
  722.  
  723. CUnicodeHubWindow::CUnicodeHubWindow(
  724.         ResIDT                inWINDid,
  725.         Uint32                inAttributes,
  726.         LCommander            *inSuperCommander) :
  727.     LWindow( inWINDid, inAttributes, inSuperCommander )
  728. {
  729.     InitUnicodeHubWindow();
  730. }
  731.  
  732.  
  733. // ---------------------------------------------------------------------------------
  734. //        • ListenToMessage
  735. // ---------------------------------------------------------------------------------
  736.  
  737. void
  738. CUnicodeHubWindow::ListenToMessage(
  739.     MessageT    inMessage,
  740.     void        *ioParam )
  741. {
  742. #pragma unused(ioParam)
  743.     
  744.     //Check if one of the check boxes was clicked on.  If so, toggle the bits in the
  745.     //appropriate control flag.
  746.     
  747.     //If the convert buttons are clicked on, the ConvertButtonHit method is called
  748.     
  749.     //If a popup menu is selected, we don't do anything about it
  750.         
  751.     if( inMessage >= kFirstFromUnicodeCheck && inMessage <=    kLastFromUnicodeCheck )
  752.     {
  753.             mFromUnicodeFlags ^= ( 1L << (inMessage - kFirstFromUnicodeCheck) );
  754.     }
  755.     else if( inMessage >= kFirstToUnicodeCheck && inMessage <=    kLastToUnicodeCheck )
  756.     {
  757.             mToUnicodeFlags ^= ( 1L << (inMessage - kFirstToUnicodeCheck) );
  758.     }        
  759.     else if( inMessage == kLeftConvertButton || inMessage == kRightConvertButton )
  760.         ConvertButtonHit( inMessage );
  761.     else if( inMessage == kLeftDisplayHex || inMessage == kRightDisplayHex )
  762.         ConvertTextToHex( inMessage );
  763.     else if( inMessage == kFontMenuPopup )
  764.     {
  765.         
  766.         CStyleText    *fromText =    (CStyleText*)FindPaneByID( kLeftText );
  767.         CStyleText    *toText =     (CStyleText*)FindPaneByID( kRightText );
  768.         CStyleText    *targetText;
  769.         
  770.         
  771.         Str31            fontName;
  772.         CFontMenuPopup*    scriptsPopup=((CFontMenuPopup*)FindPaneByID ( kFontMenuPopup ));
  773.         ScriptCode        theScript;
  774.         TextStyle         newStyle;
  775.  
  776.         theScript=scriptsPopup->GetSelectedScript();
  777.         ::KeyScript( theScript );
  778.         
  779.  
  780.         ::GetMenuItemText( scriptsPopup->GetMacMenuH(), scriptsPopup->GetValue(), fontName );
  781.         ::GetFNum(fontName, &newStyle.tsFont ) ;
  782.  
  783.         newStyle.tsSize = ::GetScriptVariable( theScript, smScriptPrefFondSize );
  784.         
  785.         if( fromText->IsTarget() )
  786.             targetText=fromText;
  787.         else if( toText->IsTarget() )
  788.             targetText=toText;
  789.         else
  790.             targetText=NULL;
  791.         
  792.         if( targetText )    
  793.         {
  794.             targetText->FocusDraw();
  795.             ::TESetStyle( doFont|doSize, &newStyle, true, targetText->GetMacTEH() );
  796.             targetText->mCurKeyScript=theScript;
  797.             ::SetScriptManagerVariable( smKeyScript, theScript );
  798.         }
  799.         
  800.     }
  801.  
  802. }
  803.  
  804. void
  805. CUnicodeHubWindow::ConvertButtonHit( MessageT    inMessage )
  806. {
  807.     LTextEdit        *fromText, *toText;
  808.     LStdCheckBox    *toCheckBox;
  809.     UInt32            fromEncoding, toEncoding;
  810.     Handle            theTextToConvert;
  811.     Handle            theConvertedText;
  812.     UInt32            sourceLen, inputRead, outputLen;
  813.     OSStatus         status;
  814.     Str255            theString;
  815.     ByteCount        convertedTextLen;
  816.     Boolean            wantHexOutput;
  817.     
  818.  
  819.     //Get the from and to text edit panel pointers as well as the value of the
  820.     //from and to encoding panel popup item selected
  821.     if ( inMessage == kLeftConvertButton )
  822.     {
  823.         fromText =    (LTextEdit*)FindPaneByID ( kLeftText );
  824.         toText =     (LTextEdit*)FindPaneByID ( kRightText );
  825.         
  826.         toCheckBox = (LStdCheckBox*)FindPaneByID ( kRightDisplayHex );
  827.         
  828.         fromEncoding =    ((CUnicodeTablesPopup*)FindPaneByID ( kLeftEncodingPopup ))->GetValue() - 1;
  829.         toEncoding =    ((CUnicodeTablesPopup*)FindPaneByID ( kRightEncodingPopup ))->GetValue() - 1;
  830.         
  831.         wantHexOutput = toCheckBox->GetValue();
  832.     }
  833.     else
  834.     {
  835.         toText =    (LTextEdit*)FindPaneByID ( kLeftText );
  836.         fromText =     (LTextEdit*)FindPaneByID ( kRightText );
  837.         
  838.         toCheckBox = (LStdCheckBox*)FindPaneByID ( kLeftDisplayHex );
  839.  
  840.         toEncoding =    ((CUnicodeTablesPopup*)FindPaneByID ( kLeftEncodingPopup ))->GetValue() - 1;
  841.         fromEncoding =    ((CUnicodeTablesPopup*)FindPaneByID ( kRightEncodingPopup ))->GetValue() - 1;
  842.         
  843.         wantHexOutput = toCheckBox->GetValue();
  844.     }
  845.     
  846.     //Get the handle to the from text and its length
  847.     theTextToConvert = fromText->GetTextHandle();
  848.     sourceLen = ::GetHandleSize(theTextToConvert);
  849.     
  850.     TEStyleHandle        theStyle=::TEGetStyleHandle( fromText->GetMacTEH() );
  851.     TextEncodingRunHdl    theRuns=0;
  852.     ByteCount**            theOffsets=0;
  853.         
  854.  
  855.     /**********************************************************************************************************
  856.      *    TEC SPECIFIC CODE COMMENT
  857.      *
  858.      *    I make my output buffers 3 times the size of the input buffers.  The reason being is that I handle
  859.      *    every single encoding out there.  There are some that require buffers larger than this depending on
  860.      *    the text that is being passed.  You don't need to make buffers so large.  You can always convert and
  861.      *    if you get kTECOutputBufferFullStatus, you need to increase you buffer size and continue the conversion
  862.      *    where it left of.  The convert code in Convert.cp shows you this.  However, by having such a large buffer
  863.      *    you should convert on the first try.  Look specifically in CPPStarterApp::ConvertFromMulti.
  864.      **********************************************************************************************************/
  865. #define SIZEOFOUTBUF    3L    
  866.     /**********************************************************************************************************
  867.      *    END TEC SPECIFIC CODE COMMENTED BLOCK
  868.      **********************************************************************************************************/
  869.  
  870.     //Create the output handle to be at SIZEOFOUTBUF times the size of the source length
  871.     theConvertedText = NewHandle( sourceLen * SIZEOFOUTBUF );
  872.     FailNIL_(theConvertedText);
  873.  
  874.     //Call the convert function
  875.     if( fromEncoding != 0 )
  876.     {
  877.          status = gTheApp->DoConvert(    theTextToConvert, sourceLen, fromEncoding,
  878.                     theConvertedText, inputRead, outputLen, convertedTextLen, toEncoding,
  879.                     theRuns, mFromUnicodeFlags, mToUnicodeFlags, wantHexOutput );
  880.         
  881.         //If the output is a single encoding, then figure out if it is a mac encoding, if so, add a run with it.
  882.         if( theRuns == 0 ) 
  883.         {
  884.             theRuns=(TextEncodingRunHdl)NewHandle(sizeof(TextEncodingRun) );
  885.             if( theRuns )
  886.             {
  887.                 ::HLock((Handle)theRuns);
  888.                 (**theRuns).textEncoding=gTheApp->mAvailableMappings[ toEncoding-1 ];
  889.                 (**theRuns).offset=0;
  890.             }
  891.         }
  892.     }
  893.     else
  894.     {
  895.         TextEncoding    unicodeEncoding;
  896.         
  897.         //Make sure that the check box is set since the output that we are going to
  898.         //get is in HEX
  899.         toCheckBox->SetValue(1);
  900.         
  901.         gTheApp->ResolveConversionParams(    NULL,      NULL,
  902.                                             toEncoding, &unicodeEncoding, NULL );
  903.         
  904.         if( gTheApp->IsUnicode( unicodeEncoding ) )        
  905.             status = gTheApp->ConvertFromMulti( unicodeEncoding, theTextToConvert, theStyle, sourceLen, theConvertedText,
  906.                     inputRead, outputLen, convertedTextLen, theOffsets, mToUnicodeFlags);
  907.         else
  908.         {
  909.             ::ParamText("\pStyled Text can only be converter to Unicode", "\p", "\p", "\p");
  910.             ::Alert(kSimpleAlert, NULL);
  911.             outputLen=0;
  912.             inputRead=0;
  913.             convertedTextLen=0;
  914.             status=paramErr;
  915.             ::SetHandleSize(theConvertedText, 0);
  916.         }
  917.     }
  918.     
  919.     //Reset the handle size of the converted text to as many bytes as were able to be converted
  920.     //and set the value of the toText LTextEdit to the converted string.
  921.     ::SetHandleSize(theConvertedText, convertedTextLen);
  922.     toText->SetTextHandle( theConvertedText );
  923.     if( theRuns )
  924.     {
  925.         TEHandle    toTextHdl=toText->GetMacTEH();
  926.         
  927.         ItemCount    noItems=GetHandleSize((Handle)theRuns)/sizeof(TextEncodingRun);
  928.         
  929.         toText->FocusDraw();
  930.  
  931.         ::HLock( (Handle)theRuns );
  932.         for(int i=0; i<noItems; i++)
  933.         {
  934.             TextStyle     newStyle;
  935.             ScriptCode    theScript;
  936.             UInt16        styleMode;
  937.             OSStatus    status2;
  938.             
  939.     /**********************************************************************************************************
  940.      *    TEC SPECIFIC CODE COMMENT
  941.      *
  942.      *    After I use ConvertUnicodeToTextRun, I examine each of the encoding runs to determine what Font to use
  943.      *    in order to display the string.  RevertTextEncodingToScriptInfo is used for this purpose.  If it 
  944.      *    returns a font name, then I use that one.  When it does, it means that it picked up on an encoding
  945.      *    run that has symbol, dingbats, vt100, or an encoding from a font/text encoding variant.  If it doesn't 
  946.      *    return a font name, I just just the preferred App font for the script.
  947.      **********************************************************************************************************/
  948.  
  949.             status2=RevertTextEncodingToScriptInfo( (*theRuns)[i].textEncoding, &theScript, NULL, theString );
  950.             if( status2 == noErr )
  951.             {
  952.                 if( *theString == 0 )
  953.                     newStyle.tsFont = ::GetScriptVariable( theScript, smScriptAppFond );
  954.                 else    
  955.                     GetFNum( theString, &newStyle.tsFont);
  956.                 newStyle.tsSize = ::GetScriptVariable( theScript, smScriptPrefFondSize );
  957.                 styleMode=doFont|doSize;
  958.             }
  959.             else
  960.             {
  961.                 theScript= ::GetScriptManagerVariable( smSysScript );
  962.                 newStyle.tsFont = ::GetScriptVariable( theScript, smScriptAppFond );
  963.                 newStyle.tsSize = ::GetScriptVariable( theScript, smScriptPrefFondSize );
  964.                 newStyle.tsFace = bold;
  965.                 styleMode=doFont|doSize|doFace;
  966.             }
  967.  
  968.             ByteCount endOffset= (i==noItems-1) ? -1 : (*theRuns)[i+1].offset;
  969.             ::TESetSelect((*theRuns)[i].offset, endOffset, toTextHdl);
  970.             ::TESetStyle(styleMode, &newStyle, true, toTextHdl );
  971.  
  972.     /**********************************************************************************************************
  973.      *    END TEC SPECIFIC CODE COMMENTED BLOCK
  974.      **********************************************************************************************************/
  975.  
  976.         }
  977.         
  978.         //Set the selection to the end of the text
  979.         ::TESetSelect(-1, -1, toTextHdl);
  980.         
  981.         ::HUnlock( (Handle)theRuns );
  982.     }
  983.     else if( theOffsets )
  984.     {
  985.         TEHandle    toTextHdl=toText->GetMacTEH();
  986.         ItemCount    noItems=GetHandleSize((Handle)theOffsets)/sizeof(ByteCount);
  987.         
  988.         toText->FocusDraw();
  989.  
  990.         ::HLock( (Handle)theOffsets );
  991.         for(int i=0; i<noItems; i++)
  992.         {
  993.             TextStyle    newStyle;
  994.                         
  995.             newStyle.tsColor.green=0;
  996.             newStyle.tsColor.red=(i%2)==1 ?  0xFFFFFFFF : 0;
  997.             newStyle.tsColor.blue =(i%2)==0 ? 0xFFFFFFFF: 0;
  998.             
  999.             
  1000.             ByteCount endOffset= (i==noItems-1) ? -1 : (*theOffsets)[i+1];
  1001.             ::TESetSelect((*theOffsets)[i], endOffset, toTextHdl);
  1002.             ::TESetStyle( doColor, &newStyle, true, toTextHdl );
  1003.         }
  1004.         ::HUnlock( (Handle)theOffsets );        
  1005.         ::DisposeHandle( (Handle)theOffsets );
  1006.         
  1007.     }
  1008.     
  1009.     //Dispose of our converted text handle
  1010.     ::DisposeHandle(theConvertedText);
  1011.  
  1012.     // convert inputRead to string
  1013.     ::NumToString(inputRead, theString);
  1014.     // display string in error pane
  1015.     SetDescriptorForPaneID( kInputReadCaption, theString);
  1016.  
  1017.     // convert outputLen to string
  1018.     ::NumToString(outputLen, theString);
  1019.     // display string in error pane
  1020.     SetDescriptorForPaneID( kOutputLenCaption, theString);
  1021.  
  1022.     // convert error to string
  1023.     if( status >= kUnicodeFirstError && status <= kIllegalHexString )
  1024.         BlockMove( UnicodeErrors[status-kUnicodeFirstError],theString, *(UnicodeErrors[status-kUnicodeFirstError])+1 );
  1025.     else
  1026.         ::NumToString(status, theString);
  1027.     // display string in error pane
  1028.     SetDescriptorForPaneID( kErrorCaption, theString);
  1029.  
  1030. }
  1031.  
  1032. void
  1033. CUnicodeHubWindow::ConvertTextToHex( MessageT    inMessage )
  1034. {
  1035.     LTextEdit        *fromText;
  1036.     UInt32            toValue;
  1037.     Handle            theTextToConvert;
  1038.     Handle            theConvertedText;
  1039.     ByteCount            sourceLen,convertedTextLen;
  1040.     //OSStatus         status;
  1041.     //Str255            theString;
  1042.     Boolean            convertOK=true;
  1043.     
  1044.     //Get the from and to text edit panel pointers as well as the value of the
  1045.     //from and to encoding panel popup item selected
  1046.     if ( inMessage == kLeftDisplayHex )
  1047.     {
  1048.         fromText =    (LTextEdit*)FindPaneByID ( kLeftText );
  1049.         toValue =    ((LStdCheckBox*)FindPaneByID ( kLeftDisplayHex ))->GetValue();
  1050.     }
  1051.     else
  1052.     {
  1053.         fromText =    (LTextEdit*)FindPaneByID ( kRightText );
  1054.         toValue =    ((LStdCheckBox*)FindPaneByID ( kRightDisplayHex ))->GetValue();
  1055.     }
  1056.     
  1057.     //Get the handle to the from text and its length
  1058.     theTextToConvert = fromText->GetTextHandle();
  1059.     sourceLen = ::GetHandleSize(theTextToConvert);
  1060.     
  1061.     //Create the output handle to be at 3 times the size of the source length
  1062.     theConvertedText = NewHandle( sourceLen * 3L );
  1063.     FailNIL_(theConvertedText);
  1064.  
  1065.     ::HLock( theTextToConvert );
  1066.     ::HLock( theConvertedText );
  1067.     
  1068.     if( toValue )
  1069.         BufToHex( (StringPtr)*theTextToConvert, (StringPtr)*theConvertedText, sourceLen, convertedTextLen, 2 );
  1070.     else
  1071.         convertOK=FromHexToString( (StringPtr)*theTextToConvert, sourceLen, (StringPtr)*theConvertedText, convertedTextLen);
  1072.         
  1073.     
  1074.     ::HUnlock( theTextToConvert );
  1075.     ::HUnlock( theConvertedText );
  1076.  
  1077.     if( convertOK )
  1078.     {
  1079.         ::SetHandleSize(theConvertedText, convertedTextLen);
  1080.         fromText->SetTextHandle( theConvertedText );
  1081.     }
  1082.     
  1083.     //Dispose of our converted text handle
  1084.     ::DisposeHandle(theConvertedText);
  1085. }
  1086.  
  1087.  
  1088.  
  1089. // *********************************************************************************
  1090. //        • String To Hex and back   Utilities
  1091. // *********************************************************************************
  1092.  
  1093.  
  1094. // ---------------------------------------------------------------------------------
  1095. //        • BufToHex
  1096. // ---------------------------------------------------------------------------------
  1097. void BufToHex( const unsigned char* src, unsigned char* dest, ByteCount    srcLen, ByteCount &destLen, UInt8    clumpSize)
  1098. {
  1099.     unsigned char    *hex=(unsigned char*)"0123456789ABCDEF";
  1100.     UInt8            tempClumpSize = clumpSize;
  1101.  
  1102.     destLen=0;
  1103.     while(srcLen--)
  1104.     {        
  1105.         *dest++ = *( hex + ((*src&0xF0)>>4) );
  1106.         *dest++ = *( hex + ( *src&0x0F ) );
  1107.         destLen+=2;
  1108.         
  1109.         if( clumpSize != 0 )
  1110.         {
  1111.             if( --tempClumpSize == 0 )
  1112.             {
  1113.                 *dest++ = ' ';
  1114.                 tempClumpSize = clumpSize;
  1115.                 destLen++;
  1116.             }
  1117.         }
  1118.         
  1119.         src++;
  1120.     }
  1121. }
  1122.  
  1123. // ---------------------------------------------------------------------------------
  1124. //        • FromHexToString
  1125. // ---------------------------------------------------------------------------------
  1126.  
  1127. #define TOUPPER(c)    ( (c>'Z') ? c & 0xDF : c )
  1128. #define ISHEX(c) ( (c>='0' && c<='9') || ( c>='A' && c<='F') )
  1129. #define HEXTONUM(c)    ( (c>'9') ? c-'A'+10 : c-'0' )
  1130.  
  1131. Boolean FromHexToString( unsigned char* str, ByteCount length, unsigned char*    dest, ByteCount &actualLen)
  1132. {
  1133.     unsigned char    high, low;
  1134.     
  1135.     actualLen = 0;
  1136.     
  1137.     while( length )
  1138.     {        
  1139.         //skip any empty spaces
  1140.         while( length && *str==' '){    str++; length--; }
  1141.         if(!length)    break;
  1142.  
  1143.         low = 0;    //initialize low to point to an impossible character
  1144.         
  1145.         //get the high byte
  1146.         high=TOUPPER(*str);
  1147.         length--;
  1148.         str++;
  1149.         
  1150.         //skip any empty spaces
  1151.         while( length && *str==' '){    str++; length--; }
  1152.         if(!length)    break;
  1153.         
  1154.         //get the low byte
  1155.         low=TOUPPER(*str);
  1156.         length--;
  1157.         str++;
  1158.         
  1159.         //convert our hex number if possible
  1160.         if( ISHEX(high) && ISHEX(low) )
  1161.         {
  1162.             *dest++=(HEXTONUM(high)<<4) | HEXTONUM(low);
  1163.             actualLen++;
  1164.         }
  1165.         else
  1166.             return false;
  1167.     }        
  1168.     
  1169.     return (low!=0);    //if low==0 then we have an incomplete hex string
  1170. }
  1171.  
  1172.  
  1173. //----------------------------------
  1174. // ---------------------------------------------------------------------------
  1175. //        • CStyleText
  1176. // ---------------------------------------------------------------------------
  1177. //    Construct from input parameters
  1178.  
  1179. CStyleText::CStyleText(
  1180.     const SPaneInfo    &inPaneInfo,
  1181.     const SViewInfo    &inViewInfo,
  1182.     Uint16            inTextAttributes,
  1183.     ResIDT            inTextTraitsID) 
  1184. {
  1185.     LView(inPaneInfo, inViewInfo);
  1186.     mTextAttributes = inTextAttributes;
  1187.     InitStyleTextEdit(inTextTraitsID);
  1188.     AlignTextEditRects();
  1189. }
  1190.  
  1191.  
  1192. // ---------------------------------------------------------------------------------
  1193. //        • CreateStyleTextEditStream
  1194. // ---------------------------------------------------------------------------------
  1195. CStyleText*
  1196. CStyleText::CreateStyleTextEditStream(LStream *inStream)
  1197. {
  1198.     return( new CStyleText( inStream ) );
  1199. }
  1200.  
  1201. // ---------------------------------------------------------------------------
  1202. //        • CStyleText(LStream*)
  1203. // ---------------------------------------------------------------------------
  1204. //    Contruct an TextEdit from the data in a Stream
  1205.  
  1206. CStyleText::CStyleText(
  1207.     LStream    *inStream)
  1208.         : LTextEdit(inStream)
  1209. {
  1210.  
  1211.     Handle    initialTextH = GetTextHandle();
  1212.     HandToHand( &initialTextH );
  1213.     
  1214.     ::TEDispose( mTextEditH );
  1215.     InitStyleTextEdit(mTextTraitsID);
  1216.     AlignTextEditRects();
  1217.     
  1218.     if (initialTextH != nil) {
  1219.         SetTextHandle(initialTextH);
  1220.         ::ReleaseResource(initialTextH);
  1221.         ::TESetSelect(0, 0, mTextEditH);
  1222.     }
  1223. }
  1224.  
  1225. // ---------------------------------------------------------------------------
  1226. //        • InitStyleTextEdit
  1227. // ---------------------------------------------------------------------------
  1228. //    Initialize member variables of a TextEdit to default values - Also overrides
  1229. //    the parent's method and creates a styled text edit record as opposed to
  1230. //    a mono-styled text
  1231.  
  1232. void
  1233. CStyleText::InitStyleTextEdit(
  1234.     ResIDT    inTextTraitsID)
  1235. {
  1236.     
  1237.     Rect    viewRect = {0, 0, 0, 0};
  1238.     mTextEditH = ::TEStyleNew(&viewRect, &viewRect);        //<JAG>
  1239.     
  1240.     mCurKeyScript = ::GetScriptManagerVariable(smKeyScript);
  1241.  
  1242.     SetTextTraitsID(inTextTraitsID);
  1243.     
  1244.         // If word wrap is on, then the Image width is always the
  1245.         // same as the Frame width, which forces text to wrap to
  1246.         // the Frame.
  1247.         
  1248.         // If the Image width is zero (or negative), the user
  1249.         // probably forgot to set it. To accommodate this error,
  1250.         // we set the Image width to the Frame width. However, the
  1251.         // Image will not change if the Frame resizes.
  1252.     
  1253.     if ((mTextAttributes & textAttr_WordWrap) ||
  1254.         (mImageSize.width <= 0)) {
  1255.         mImageSize.width = mFrameSize.width;
  1256.     }
  1257. }
  1258.  
  1259. Boolean
  1260. CStyleText::FocusDraw()
  1261. {
  1262.     
  1263.     Boolean    focused = LView::FocusDraw();
  1264.     if (focused) {
  1265.         StColorPenState::Normalize();
  1266.     }
  1267.     
  1268.     return focused;
  1269. }
  1270.  
  1271.  
  1272. // ---------------------------------------------------------------------------
  1273. //        SpendTime
  1274. // ---------------------------------------------------------------------------
  1275. //    Here we make sure that the keyScript and the sysKeyScript are in sync
  1276. //    If they aren't we set the keyScript to be that of the sysKeyScript.
  1277. //    We don't do the later if there is a selection that goes accross multiple 
  1278. //    runs
  1279. void
  1280. CStyleText::SpendTime(const EventRecord &inMacEvent)
  1281. {
  1282.         
  1283.     LTextEdit::SpendTime( inMacEvent );
  1284.     
  1285.     if( mCurKeyScript != ::GetScriptManagerVariable(smKeyScript) )
  1286.     {
  1287.     
  1288.         UInt16        noStyles=1;
  1289.         
  1290.         if( (**mTextEditH).selStart != (**mTextEditH).selEnd )
  1291.         {
  1292.             StScrpHandle    sTE=TEGetStyleScrapHandle(mTextEditH);
  1293.             
  1294.             noStyles=(**sTE).scrpNStyles;
  1295.             
  1296.             DisposeHandle((Handle)sTE);
  1297.         }
  1298.             
  1299.         if( noStyles == 1 )
  1300.         {
  1301.             mCurKeyScript = ::GetScriptManagerVariable(smKeyScript);
  1302.             
  1303.             CFontMenuPopup*    fontMenuPopup=(CFontMenuPopup*)(GetDefaultView()->FindPaneByID ( kFontMenuPopup ));
  1304.             if( fontMenuPopup )
  1305.                 fontMenuPopup->SetMValue( (ScriptCode) mCurKeyScript );
  1306.         }
  1307.     }
  1308. }
  1309.  
  1310.  
  1311. // ---------------------------------------------------------------------------
  1312. //        ObeyCommand
  1313. // ---------------------------------------------------------------------------
  1314. //    Here we handle Styled Text copy and paste which the original PP methods dont
  1315. //    handle or that have bus in them.
  1316. Boolean
  1317. CStyleText::ObeyCommand(
  1318.     CommandT    inCommand,
  1319.     void*        ioParam)
  1320. {
  1321.     Boolean        cmdHandled = true;
  1322.     
  1323.     switch (inCommand) {
  1324.         Handle    teScrap=TEScrapHandle();
  1325.             
  1326.         case cmd_Cut:
  1327.             ::ZeroScrap();            //Bug in powerplant.  ZeroScrap should be called before TECut
  1328.             ::TECut(mTextEditH);
  1329.             ::TEToScrap();
  1330.             AdjustImageToText();
  1331.             UserChangedText();
  1332.             break;
  1333.             
  1334.         case cmd_Copy:
  1335.             ::ZeroScrap();            //Bug in powerplant.  ZeroScrap should be called before TECopy
  1336.             ::TECopy(mTextEditH);
  1337.             ::TEToScrap();
  1338.             break;
  1339.  
  1340.         case cmd_Paste:
  1341.             ::TEFromScrap();
  1342.             ::TEStylePaste(mTextEditH);
  1343.             AdjustImageToText();
  1344.             UserChangedText();
  1345.             break;
  1346.             
  1347.             
  1348.         default:
  1349.             cmdHandled = LTextEdit::ObeyCommand(inCommand, ioParam);
  1350.             break;
  1351.     }
  1352.     
  1353.     return cmdHandled;
  1354. }
  1355.  
  1356. // ---------------------------------------------------------------------------
  1357. //        Click
  1358. // ---------------------------------------------------------------------------
  1359. //    Here we make a font selection depending where in the text the user click.
  1360. //    We want our font menu to have the correct font displayed.  If the click 
  1361. //    yields a selection that spreads accross multiple style runs, then we
  1362. //    do not change the font selection.  We should probably have a menu item
  1363. //    in the font menu that is blank to indicate to the user that there isn't 
  1364. //    one possible selection to be made.
  1365. void
  1366. CStyleText::Click( SMouseDownEvent        &inMouseDown) 
  1367. {
  1368.     LTextEdit::Click( inMouseDown );
  1369.     TextStyle            theStyle;
  1370.     
  1371.     
  1372.     CFontMenuPopup*    fontMenuPopup=(CFontMenuPopup*)(GetDefaultView()->FindPaneByID ( kFontMenuPopup ));
  1373.     
  1374.     SInt16        lineHeight;
  1375.     SInt16        ascend;
  1376.     UInt16        offset;
  1377.     
  1378.     UInt16        noStyles=1;
  1379.     
  1380.     if( (**mTextEditH).selStart != (**mTextEditH).selEnd )
  1381.     {
  1382.         StScrpHandle    sTE=TEGetStyleScrapHandle(mTextEditH);
  1383.         
  1384.         noStyles=(**sTE).scrpNStyles;
  1385.         
  1386.         DisposeHandle((Handle)sTE);
  1387.     }
  1388.         
  1389.     if( noStyles == 1 )
  1390.     {
  1391.         offset=::TEGetOffset( inMouseDown.whereLocal, mTextEditH );
  1392.         ::TEGetStyle( offset, &theStyle, &lineHeight, &ascend, mTextEditH);
  1393.         
  1394.         if( theStyle.tsFont == applFont )
  1395.             theStyle.tsFont = GetAppFont();
  1396.         if( fontMenuPopup->mInstalledFonts[fontMenuPopup->GetValue()-1] != theStyle.tsFont )
  1397.         {
  1398.             fontMenuPopup->SetValueByFont( theStyle.tsFont );
  1399.             mCurKeyScript=::FontToScript(theStyle.tsFont);
  1400.             ::SetScriptManagerVariable(smKeyScript, mCurKeyScript);
  1401.  
  1402.         }
  1403.     }
  1404. }
  1405.     
  1406.  
  1407.  
  1408. // ---------------------------------------------------------------------------
  1409. //        BeTarget
  1410. // ---------------------------------------------------------------------------
  1411. //    Here we make sure that the keyScript and the current font selected for the
  1412. //    text edit field being targeted is the same
  1413. void
  1414. CStyleText::BeTarget()
  1415. {
  1416.     CFontMenuPopup*    fontMenuPopup=(CFontMenuPopup*)(GetDefaultView()->FindPaneByID ( kFontMenuPopup ));
  1417.     if( fontMenuPopup )
  1418.     {
  1419.         ScriptCode    theScript=(fontMenuPopup)->GetSelectedScript();
  1420.         
  1421.         if( theScript != mCurKeyScript )
  1422.         {
  1423.             fontMenuPopup->SetMValue( (ScriptCode) mCurKeyScript );
  1424.         }
  1425.     }
  1426.  
  1427.     LTextEdit::BeTarget();
  1428. }
  1429.